package service

import (
	"errors"
	"strings"
	"time"

	"pool/pool_backend/internal/models"
	"pool/pool_backend/internal/repository"
	"pool/pool_backend/pkg/logger"
)

// ClaimService Claim服务接口
type ClaimService interface {
	// GetClaimRecords 获取用户的Claim记录
	GetClaimRecords(address string) ([]*models.ClaimResponse, error)
	// GetClaimableAmount 获取用户可以claim的数量
	GetClaimableAmount(address string) (int, error)
	// RecordCheckIn 记录用户Check-In
	RecordCheckIn(address, hash string) error
	// UpdateAncestorRewards 更新祖先奖励
	UpdateAncestorRewards(address string) error
	// ClaimLevelToken 领取层级奖励
	ClaimLevelToken(address, hash string) (int, error)
}

// claimServiceImpl Claim服务实现
type claimServiceImpl struct {
	userRepo  repository.UserRepository
	claimRepo repository.ClaimRepository
}

// NewClaimService 创建Claim服务
func NewClaimService(userRepo repository.UserRepository, claimRepo repository.ClaimRepository) ClaimService {
	return &claimServiceImpl{
		userRepo:  userRepo,
		claimRepo: claimRepo,
	}
}

// GetClaimRecords 获取用户的Claim记录
func (s *claimServiceImpl) GetClaimRecords(address string) ([]*models.ClaimResponse, error) {
	// 检查地址格式
	if len(address) != 42 || address[:2] != "0x" {
		return nil, errors.New("invalid address format")
	}

	// 检查用户是否存在
	user, err := s.userRepo.GetUserByAddress(address)
	if err != nil {
		logger.ErrorF("Failed to get user: %v", err)
		return nil, err
	}
	if user == nil {
		return nil, errors.New("user not found")
	}

	// 获取Claim记录
	records, err := s.claimRepo.GetClaimRecords(address)
	if err != nil {
		logger.ErrorF("Failed to get claim records: %v", err)
		return nil, err
	}

	return records, nil
}

// RecordCheckIn 记录用户Check-In
func (s *claimServiceImpl) RecordCheckIn(address, hash string) error {
	// 检查地址格式
	if len(address) != 42 || address[:2] != "0x" {
		return errors.New("invalid address format")
	}

	// 检查哈希格式
	if len(hash) != 66 || hash[:2] != "0x" {
		return errors.New("invalid hash format")
	}

	// 检查用户是否存在
	user, err := s.userRepo.GetUserByAddress(address)
	if err != nil {
		logger.ErrorF("Failed to get user: %v", err)
		return err
	}
	if user == nil {
		// 创建用户
		user = &models.User{
			Address:     address,
			LastCheckIn: time.Now(),
			LastCheck:   time.Now(),
		}
		err = s.userRepo.CreateUser(user)
		if err != nil {
			logger.ErrorF("Failed to create user: %v", err)
			return err
		}
	} else {
		// 更新用户最后Check-In时间
		user.LastCheckIn = time.Now()
		err = s.userRepo.UpdateUser(user)
		if err != nil {
			logger.ErrorF("Failed to update user: %v", err)
			return err
		}
	}

	// 创建Check-In记录
	checkInRecord := &models.CheckInRecord{
		UserAddress: address,
		CheckInTime: time.Now(),
		Hash:        hash,
	}
	err = s.claimRepo.CreateCheckInRecord(checkInRecord)
	if err != nil {
		logger.ErrorF("Failed to create check-in record: %v", err)
		return err
	}

	// 更新祖先奖励
	err = s.UpdateAncestorRewards(address)
	if err != nil {
		logger.ErrorF("Failed to update ancestor rewards: %v", err)
		// 不返回错误，继续执行
	}

	return nil
}

// UpdateAncestorRewards 更新祖先奖励
func (s *claimServiceImpl) UpdateAncestorRewards(address string) error {
	// 获取用户
	user, err := s.userRepo.GetUserByAddress(address)
	if err != nil {
		return err
	}
	if user == nil || user.Ancestors == "" {
		return nil // 没有祖先，直接返回
	}

	// 解析祖先链，格式为：parent,grandparent,great-grandparent,...
	ancestors := strings.Split(user.Ancestors, ",")
	if len(ancestors) == 0 {
		return nil
	}

	// 逐层处理祖先奖励
	for i, ancestorAddr := range ancestors {
		if i >= 10 {
			break // 最多处理10层
		}

		// 获取祖先
		ancestor, err := s.userRepo.GetUserByAddress(ancestorAddr)
		if err != nil {
			logger.ErrorF("Failed to get ancestor: %v", err)
			continue
		}
		if ancestor == nil {
			continue
		}

		// 获取祖先的邀请人数
		inviteeCount, err := s.userRepo.GetInviteeCount(ancestorAddr)
		if err != nil {
			logger.ErrorF("Failed to get invitee count: %v", err)
			continue
		}

		// 如果已邀请人数小于当前层级+1，则无法获得该层级奖励
		if inviteeCount < int64(i+1) {
			continue
		}

		// 计算该层级应得的奖励
		var reward int64
		switch i {
		case 0: // 第1层
			reward = 5000
		case 1: // 第2层
			reward = 3000
		case 2: // 第3层
			reward = 600
		default: // 第4-10层
			reward = 200
		}

		// 更新祖先的总奖励和代币数量
		ancestor.Token += reward
		ancestor.TotalLevelToken += reward
		err = s.userRepo.UpdateUser(ancestor)
		if err != nil {
			logger.ErrorF("Failed to update ancestor: %v", err)
		} else {
			logger.InfoF("Updated ancestor %s reward: +%d at level %d", ancestorAddr, reward, i+1)
		}

		// 创建Claim记录
		claimRecord := &models.ClaimRecord{
			UserAddress: ancestorAddr,
			Amount:      reward,
			ClaimTime:   time.Now(),
			Hash:        "", // 无交易哈希
		}
		err = s.claimRepo.CreateClaimRecord(claimRecord)
		if err != nil {
			logger.ErrorF("Failed to create claim record: %v", err)
		}
	}

	return nil
}

// GetClaimableAmount 获取用户可以claim的数量
func (s *claimServiceImpl) GetClaimableAmount(address string) (int, error) {
	// 检查地址格式
	if len(address) != 42 || address[:2] != "0x" {
		return 0, errors.New("invalid address format")
	}

	// 获取用户
	user, err := s.userRepo.GetUserByAddress(address)
	if err != nil {
		logger.ErrorF("Failed to get user: %v", err)
		return 0, err
	}
	if user == nil {
		return 0, errors.New("user not found")
	}

	// 计算可领取的奖励 = 总奖励 - 已领取奖励
	claimableAmount := user.TotalLevelToken - user.ClaimLevelToken

	// 确保返回的是正数
	if claimableAmount < 0 {
		claimableAmount = 0
	}

	return int(claimableAmount), nil
}

// ClaimLevelToken 领取层级奖励后的处理逻辑
func (s *claimServiceImpl) ClaimLevelToken(address, hash string) (int, error) {
	// 检查地址格式
	if len(address) != 42 || address[:2] != "0x" {
		return 0, errors.New("invalid address format")
	}

	// 检查哈希格式
	if len(hash) != 66 || hash[:2] != "0x" {
		return 0, errors.New("invalid hash format")
	}

	// 获取用户
	user, err := s.userRepo.GetUserByAddress(address)
	if err != nil {
		logger.ErrorF("Failed to get user: %v", err)
		return 0, err
	}
	if user == nil {
		return 0, errors.New("user not found")
	}

	// 计算可领取的奖励
	claimableAmount := user.TotalLevelToken - user.ClaimLevelToken
	if claimableAmount <= 0 {
		return 0, errors.New("no rewards to claim")
	}

	// 更新用户已领取的奖励
	user.ClaimLevelToken = user.TotalLevelToken
	err = s.userRepo.UpdateUser(user)
	if err != nil {
		logger.ErrorF("Failed to update user: %v", err)
		return 0, err
	}

	// 创建Claim记录
	claimRecord := &models.ClaimRecord{
		UserAddress: address,
		Amount:      claimableAmount,
		ClaimTime:   time.Now(),
		Hash:        hash,
	}
	err = s.claimRepo.CreateClaimRecord(claimRecord)
	if err != nil {
		logger.ErrorF("Failed to create claim record: %v", err)
		// 不影响主流程，继续执行
	}

	logger.InfoF("User %s claimed %d level tokens", address, claimableAmount)
	return int(claimableAmount), nil
}